package queteapuesto.model.aop2;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.jmi.reflect.RefException;
import org.openmdx.base.aop2.AbstractObject;

import queteapuesto.model.cci2.Bet;
import queteapuesto.model.cci2.GameEventComponent;
import queteapuesto.model.cci2.GameEventComponentQuery;
import queteapuesto.model.cci2.GameEventQuery;
import queteapuesto.model.cci2.GameQuery;
import queteapuesto.model.cci2.UserQuery;
import queteapuesto.model.jmi1.BetServicesDoBetParams;
import queteapuesto.model.jmi1.BetServicesDoBetResult;
import queteapuesto.model.jmi1.Game;
import queteapuesto.model.jmi1.GameEvent;
import queteapuesto.model.cci2.Credit;
import queteapuesto.model.jmi1.ModelPackage;

public class BetServicesImpl 
<S extends queteapuesto.model.jmi1.BetServices, 
 N extends queteapuesto.model.cci2.BetServices, 
 C extends Void>
extends AbstractObject<S, N, C> {

	public BetServicesImpl(S same, N next) {
		super(same, next);
	}
	
	public BetServicesDoBetResult doBet(BetServicesDoBetParams in) throws RefException {
		ModelPackage modelPackage = (ModelPackage)this.sameObject().refImmediatePackage();
		UserQuery userQuery = modelPackage.createUserQuery();
		userQuery.name().equalTo(in.getUserName());
		List<queteapuesto.model.jmi1.User> users = 
			this.sameObject().getUser(userQuery);
		queteapuesto.model.jmi1.User anUser = users.get(0);
		Credit availableCredit = anUser.getCredit().iterator().next();
		BetServicesDoBetResult res = null;
		// el usuario tiene el credito suficiente.
		if(availableCredit.getAmount().compareTo(in.getAmount()) != -1) {
			// usuario tiene credito. Le descontamos la apuesta.
			queteapuesto.model.jmi1.Credit credit = modelPackage.getCredit().createCredit();
			credit.setAmount(availableCredit.getAmount().subtract(in.getAmount()));
			// TODO : asegurar que solo disponga de un "Credit"
			// de una manera mas elegante.
			anUser.getCredit().removeAll(anUser.getCredit());
			anUser.addCredit(credit);
			
			// creo la apuesta.
			queteapuesto.model.jmi1.Bet userBet = modelPackage.getBet().createBet();
			GameQuery gameQuery = modelPackage.createGameQuery();
			gameQuery.identity().equalTo(in.getGameIdentity());
			List<Game> games = this.sameObject().getGame(gameQuery);
			// ERROR : no existe el game. TODO: Mensaje.
			if(games.isEmpty()) {
				return res;
			}
			Game theGame = games.get(0);
			userBet.setGame(theGame);
			
			// me traigo todos los eventos para el game.
			Iterator<queteapuesto.model.cci2.GameEvent> itGameEvents = theGame.getGameEvent().iterator();
			boolean evtCmpFound = false;
			long timeOfBet = System.currentTimeMillis();
			while(! evtCmpFound && itGameEvents.hasNext()) {
				queteapuesto.model.cci2.GameEvent aGameEvent = itGameEvents.next();
				Iterator<queteapuesto.model.cci2.GameEventComponent> itGameEventComponents = 
						aGameEvent.getGameEventComponent().iterator();
				while( ! evtCmpFound && itGameEventComponents.hasNext()) {
					GameEventComponent aGameEvtComp = itGameEventComponents.next();
					if(aGameEvtComp.getDescription().equals(in.getGameEventComponentDescription())) {
						evtCmpFound = true;
						// si vencio reboto la apuesta
						if(timeOfBet > aGameEvtComp.getExpires()) {
							// TODO : agregar info al resultado. Por ahora es nulo.
							//return res;
							return null;
						}
						userBet.setGameEventComponent(aGameEvtComp);
					}
				}
			}
			
			userBet.setMount(in.getAmount());
			userBet.setDate(timeOfBet);		
			anUser.addBet(userBet);
			res = modelPackage.createBetServicesDoBetResult();
		}
		
		return res;
	}
}
